package com.spudtech.tween
{
    
    import com.spudtech.*;
    
    public class SpudTween
    {
        
        // Play the tween once
        public static const PLAY_ONCE : uint = 0;
        // Repeat the tween until it is stopped
        public static const REPEAT : uint = 1;
        // Play the tween, then rewind it, then stop
        public static const REVERSE_ONCE : uint = 2;
        // Play the tween, rewind it, and repeat that until stopped
        public static const REPEAT_REVERSE : uint = 3;
        
        // Callback that is called once when the tween completes
        public var callback : Function;
        
        // Easer function. Not used yet.
        public var easer : Function;
        
        // Progress through the tween
        protected var _step : uint;
        
        // The number of steps
        protected var _stepCount : uint;
        
        // Whether the tween is running
        public var running : Boolean;
        
        // The tween's play mode. (See constants above)
        public var playMode : uint;
        
        public function SpudTween(step_count : uint,
                              play_mode : uint = PLAY_ONCE,
                              init_easer : Function = null,
                              init_callback : Function = null)
        {
            _step = 0;
            _stepCount = step_count;
            
            playMode = play_mode;
            
            callback = init_callback;
            easer = init_easer;
            
        }
        
        
        public function get step() : uint
        {
            return _step;
        }
        public function set step(new_step : uint) : void
        {
            if (new_step != _step)
            {
                // It's a different step
                running = false;
            }
            else
            {
                // It's the same step
                // We can stop here
                return;
            }
            
            if (new_step > stepCount)
            {
                if (playMode == PLAY_ONCE)
                {
                    // We've hit our limit
                    
                    _step = stepCount;
                    
                    return;
                    
                }
                else if (playMode == REPEAT)
                {
                    // We loop around
                    
                    _step = new_step;
                    
                    while (_step > stepCount)
                    {
                        _step -= stepCount;
                    }
                    
                    return;
                    
                }
            }
            
            // If we're here, then either the
            // new step is less than our step
            // count or we are playing in a
            // mode that reverses
            
            if (_step > (stepCount * 2))
            {
                // Play modes that reverse will
                // go for twice the step count,
                // going in reverse during the
                // second half of it.
                
                if (playMode == REVERSE_ONCE)
                {
                    // We've been there and back
                    
                    _step = stepCount * 2;
                    
                    return;
                    
                }
                else if (playMode == REPEAT_REVERSE)
                {
                    // We loop around
                    
                    _step = new_step;
                    
                    return;
                    
                }
                else
                {
                    // Um, well, shit.
                    
                    return;
                    
                }
            }
            
            // Okay, if we're here, then
            // neither of the above if
            // blocks were entered, so
            // we know that the new_step
            // is less than or equal to
            // our step count
            
            _step = new_step;
            
        }
        
        
        public function get stepCount() : uint
        {
            return _stepCount;
            
        }
        public function set stepCount(new_count : uint) : void
        {
            _stepCount = new_count;
        }
        
        
        public function update() : void
        {
            if (running)
            {
                _step++;
                
                if (step >= stepCount &&
                    (playMode == PLAY_ONCE || playMode == REPEAT))
                {
                    
                    if (playMode == PLAY_ONCE)
                    {
                        step = stepCount;
                        running = false;
                        
                    }
                    else
                    {
                        // Looking at the above,
                        // we know that our play
                        // mode is REPEAT
                        step = 0;
                        running = true;
                        
                    }
                    
                    // Either way, we use the
                    // callback
                    if (callback != null)
                    {
                        callback();
                    }
                    
                }
                else if (step >= (stepCount * 2) &&
                         (playMode == REVERSE_ONCE ||
                          playMode == REPEAT_REVERSE))
                {
                    // Play modes that reverse
                    // run until the step is
                    // at twice the step count,
                    // going backwards through
                    // the second half of that.
                    
                    if (playMode == REVERSE_ONCE)
                    {
                        step = 0;
                        running = false;
                        
                    }
                    else
                    {
                        // We must be in REPEAT_REVERSE mode
                        step = 0;
                        running = true;
                        
                    }
                    
                    // Either way, the callback
                    if (callback != null)
                    {
                        callback();
                    }
                    
                }
                
            }
            
        }
        
    }
    
}
